package Server;

import Klient.Message;
import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.LinkedList;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 *
 * @author Martin Strouhal
 */
public class ServerCommunicator implements AbstractServerCommunicator {

    private ServerSocket serverSocket;
    private boolean start = false;
    final private static String serversWelcomeMessage = "Hello, I am totne";
    final private static int port = 55555;
    private LinkedList<OutputStream> outputStreamsOfKlients;
    private LinkedList<InputStream> inputStreamsOfKlients = null;
    private LinkedList<ObjectOutputStream> objectoutputStreamOfKlients;
    final public static String badWelcomeMessage = "Bad welcome message";
    final public static String klientAdded = "Klient added successfully";
    private Thread prijemZprav;

    /**
     * Odesílá zprávy.
     *
     * @param m zpráva k odeslání
     */
    @Override
    public void sendMessage(Message m) {
        for (int i = 0; i < objectoutputStreamOfKlients.size(); i++) {
            try {
                objectoutputStreamOfKlients.get(i).writeObject(m);
            } catch (IOException ex) {
                System.out.println(ex.getMessage());
            }
        }
    }

    /**
     * Spustí server.
     */
    public void initServer() {
        try {
            serverSocket = new ServerSocket(port);
        } catch (IOException ex) {
            System.out.println(ex + " from ServerCommunicator -> initServer");
        }
        prijemZprav = new Thread(new Runnable() {

            @Override
            public void run() {
                LinkedList<ObjectInputStream> linkedListOfOIS = null;
                while (inputStreamsOfKlients == null) {
                }
                for (int i = 0; i < inputStreamsOfKlients.size(); i++) {
                    try {
                        linkedListOfOIS.add(new ObjectInputStream(inputStreamsOfKlients.get(i)));
                    } catch (IOException ex) {
                        System.out.println(ex.getMessage());
                    }
                }
                while (true) {
                    for (int i = 0; i < linkedListOfOIS.size(); i++) {
                        try {
                            process((Message) linkedListOfOIS.get(i).readObject());
                        } catch (IOException | ClassNotFoundException ex) {
                            System.out.println(ex.getMessage());
                        }
                    }
                }
            }
        });
        prijemZprav.start();
        Thread threadPripojeniKlientu = new Thread(new Runnable() {

            @Override
            public void run() {
                MulticastServerThread mst = new MulticastServerThread();
                mst.start();
                while (start) {
                    try {
                        verify(serverSocket.accept());
                    } catch (IOException ex) {
                        System.out.println(ex.getMessage() + " from ServerCommunicator -> initServer");
                    }
                }
                mst.setDalsiPozadavky(false);
            }
        });
        threadPripojeniKlientu.start();
    }

    private void addKlient(InputStream is, OutputStream os) {//přidá klienta
        inputStreamsOfKlients.add(is);
        outputStreamsOfKlients.add(os);
        try {
            objectoutputStreamOfKlients.add(new ObjectOutputStream(os));
        } catch (IOException ex) {
            System.out.println(ex.getMessage());
        }
        PrintWriter writer = null;
        writer = new PrintWriter(new OutputStreamWriter(os));
        writer.write(klientAdded);
        writer.flush();
    }

    /**
     * Ověří, zda může být klient přijat.
     *
     * @param socket - určitý klient, který bude ověřen
     */
    @Override
    public void verify(Socket socket) {
        if (socket != null) {
            BufferedReader reader = null;
            String welcomeMessage = null;
            InputStream is = null;
            OutputStream os = null;
            try {
                is = socket.getInputStream();
            } catch (IOException ex) {
                System.out.println(ex.getMessage());
            }
            reader = new BufferedReader(new InputStreamReader(is));
            try {
                welcomeMessage = reader.readLine();
            } catch (IOException ex) {
                System.out.println(ex.getMessage());
            }

            if (welcomeMessage.compareTo(serversWelcomeMessage) == 0) {
                addKlient(is, os);
            } else {
                BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(os));
                try {
                    writer.write(badWelcomeMessage);
                } catch (IOException ex) {
                    System.out.println(ex.getMessage());
                }
                try {
                    writer.flush();
                } catch (IOException ex) {
                    System.out.println(ex.getMessage());
                }
                try {
                    writer.close();
                } catch (IOException ex) {
                    System.out.println(ex.getMessage());
                }
            }
        }
    }

    private void process(Message m) {
        throw new UnsupportedOperationException("Not supported yet.");
    }
}